Skip to main content

Define Contract States

In this section, we will define the states for the LotteryGame contract, which includes setting up the contract logic states and the reference state for the MultiToken contract.

Step 1: Defining Contract Logic States

Instructions

  1. Open the file: Navigate to the src directory and open the LotteryGameState.cs file.

  2. Replace the contents: Replace the existing contents of the file with the following code snippet. This snippet defines the necessary states for the LotteryGame contract.

using AElf.Sdk.CSharp.State;
using AElf.Types;

namespace AElf.Contracts.LotteryGame
{
// The state class is access the blockchain state
public partial class LotteryGameState : ContractState
{
// A state to check if contract is initialized
public BoolState Initialized { get; set; }
// A state to store the owner address
public SingletonState<Address> Owner { get; set; }
}
}

Explanation

  • The using AElf.Sdk.CSharp.State; and using AElf.Types; directives import the necessary namespaces for defining contract states and working with AElf types.
  • The LotteryGameState class inherits from ContractState, which allows it to access the blockchain state.
  • The Initialized property is of type BoolState, which is used to track whether the contract has been initialized before.
  • The Owner property is of type SingletonState<Address>, which stores the owner's address.

Step 2: Defining Contract Reference State

Next, we will set up a reference to the MultiToken contract within our LotteryGame contract.

Step 2.1: Creating Multitoken Contract proto file

Instructions

  1. Create a new file: Navigate to your project's src/Protobuf/reference directory. If this directory doesn't exist, create it. Within this directory, create a new file named token_contract.proto.

  2. Import the MultiToken Contract's proto file: Copy and paste the following code snippet into the newly created token_contract.proto file. This code imports the MultiToken Contract's definitions.

/**
* MultiToken contract.
*/
syntax = "proto3";

package token;

import "aelf/core.proto";
import "aelf/options.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/wrappers.proto";

option csharp_namespace = "AElf.Contracts.MultiToken";

service TokenContract {
// Create a new token.
rpc Create (CreateInput) returns (google.protobuf.Empty) {
}

// Issuing some amount of tokens to an address is the action of increasing that addresses balance
// for the given token. The total amount of issued tokens must not exceed the total supply of the token
// and only the issuer (creator) of the token can issue tokens.
// Issuing tokens effectively increases the circulating supply.
rpc Issue (IssueInput) returns (google.protobuf.Empty) {
}

// Transferring tokens simply is the action of transferring a given amount of tokens from one address to another.
// The origin or source address is the signer of the transaction.
// The balance of the sender must be higher than the amount that is transferred.
rpc Transfer (TransferInput) returns (google.protobuf.Empty) {
}

// The TransferFrom action will transfer a specified amount of tokens from one address to another.
// For this operation to succeed the from address needs to have approved (see allowances) enough tokens
// to Sender of this transaction. If successful the amount will be removed from the allowance.
rpc TransferFrom (TransferFromInput) returns (google.protobuf.Empty) {
}

// The approve action increases the allowance from the Sender to the Spender address,
// enabling the Spender to call TransferFrom.
rpc Approve (ApproveInput) returns (google.protobuf.Empty) {
}

rpc BatchApprove (BatchApproveInput) returns (google.protobuf.Empty) {
}

// This is the reverse operation for Approve, it will decrease the allowance.
rpc UnApprove (UnApproveInput) returns (google.protobuf.Empty) {
}

// This method can be used to lock tokens.
rpc Lock (LockInput) returns (google.protobuf.Empty) {
}

// This is the reverse operation of locking, it un-locks some previously locked tokens.
rpc Unlock (UnlockInput) returns (google.protobuf.Empty) {
}

// This action will burn the specified amount of tokens, removing them from the token’s Supply.
rpc Burn (BurnInput) returns (google.protobuf.Empty) {
}

// Set the primary token of side chain.
rpc SetPrimaryTokenSymbol (SetPrimaryTokenSymbolInput) returns (google.protobuf.Empty) {
}

// This interface is used for cross-chain transfer.
rpc CrossChainTransfer (CrossChainTransferInput) returns (google.protobuf.Empty) {
}

// This method is used to receive cross-chain transfers.
rpc CrossChainReceiveToken (CrossChainReceiveTokenInput) returns (google.protobuf.Empty) {
}

// The side chain creates tokens.
rpc CrossChainCreateToken(CrossChainCreateTokenInput) returns (google.protobuf.Empty) {
}

// When the side chain is started, the side chain is initialized with the parent chain information.
rpc InitializeFromParentChain (InitializeFromParentChainInput) returns (google.protobuf.Empty) {
}

// Handle the transaction fees charged by ChargeTransactionFees.
rpc ClaimTransactionFees (TotalTransactionFeesMap) returns (google.protobuf.Empty) {
}

// Used to collect transaction fees.
rpc ChargeTransactionFees (ChargeTransactionFeesInput) returns (ChargeTransactionFeesOutput) {
}

rpc ChargeUserContractTransactionFees(ChargeTransactionFeesInput) returns(ChargeTransactionFeesOutput){

}

// Check the token threshold.
rpc CheckThreshold (CheckThresholdInput) returns (google.protobuf.Empty) {
}

// Initialize coefficients of every type of tokens supporting charging fee.
rpc InitialCoefficients (google.protobuf.Empty) returns (google.protobuf.Empty){
}

// Processing resource token received.
rpc DonateResourceToken (TotalResourceTokensMaps) returns (google.protobuf.Empty) {
}

// A transaction resource fee is charged to implement the ACS8 standards.
rpc ChargeResourceToken (ChargeResourceTokenInput) returns (google.protobuf.Empty) {
}

// Verify that the resource token are sufficient.
rpc CheckResourceToken (google.protobuf.Empty) returns (google.protobuf.Empty) {
}

// Set the list of tokens to pay transaction fees.
rpc SetSymbolsToPayTxSizeFee (SymbolListToPayTxSizeFee) returns (google.protobuf.Empty){
}

// Update the coefficient of the transaction fee calculation formula.
rpc UpdateCoefficientsForSender (UpdateCoefficientsInput) returns (google.protobuf.Empty) {
}

// Update the coefficient of the transaction fee calculation formula.
rpc UpdateCoefficientsForContract (UpdateCoefficientsInput) returns (google.protobuf.Empty) {
}

// This method is used to initialize the governance organization for some functions,
// including: the coefficient of the user transaction fee calculation formula,
// the coefficient of the contract developer resource fee calculation formula, and the side chain rental fee.
rpc InitializeAuthorizedController (google.protobuf.Empty) returns (google.protobuf.Empty){
}

rpc AddAddressToCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) {
}
rpc RemoveAddressFromCreateTokenWhiteList (aelf.Address) returns (google.protobuf.Empty) {
}

rpc SetTransactionFeeDelegations (SetTransactionFeeDelegationsInput) returns (SetTransactionFeeDelegationsOutput){
}

rpc RemoveTransactionFeeDelegator (RemoveTransactionFeeDelegatorInput) returns (google.protobuf.Empty){
}

rpc RemoveTransactionFeeDelegatee (RemoveTransactionFeeDelegateeInput) returns (google.protobuf.Empty){
}

rpc SetSymbolAlias (SetSymbolAliasInput) returns (google.protobuf.Empty){
}

// Get all delegatees' address of delegator from input
rpc GetTransactionFeeDelegatees (GetTransactionFeeDelegateesInput) returns (GetTransactionFeeDelegateesOutput) {
option (aelf.is_view) = true;
}

// Query token information.
rpc GetTokenInfo (GetTokenInfoInput) returns (TokenInfo) {
option (aelf.is_view) = true;
}

// Query native token information.
rpc GetNativeTokenInfo (google.protobuf.Empty) returns (TokenInfo) {
option (aelf.is_view) = true;
}

// Query resource token information.
rpc GetResourceTokenInfo (google.protobuf.Empty) returns (TokenInfoList) {
option (aelf.is_view) = true;
}

// Query the balance at the specified address.
rpc GetBalance (GetBalanceInput) returns (GetBalanceOutput) {
option (aelf.is_view) = true;
}

// Query the account's allowance for other addresses
rpc GetAllowance (GetAllowanceInput) returns (GetAllowanceOutput) {
option (aelf.is_view) = true;
}

// Query the account's available allowance for other addresses
rpc GetAvailableAllowance (GetAllowanceInput) returns (GetAllowanceOutput) {
option (aelf.is_view) = true;
}

// Check whether the token is in the whitelist of an address,
// which can be called TransferFrom to transfer the token under the condition of not being credited.
rpc IsInWhiteList (IsInWhiteListInput) returns (google.protobuf.BoolValue) {
option (aelf.is_view) = true;
}

// Query the information for a lock.
rpc GetLockedAmount (GetLockedAmountInput) returns (GetLockedAmountOutput) {
option (aelf.is_view) = true;
}

// Query the address of receiving token in cross-chain transfer.
rpc GetCrossChainTransferTokenContractAddress (GetCrossChainTransferTokenContractAddressInput) returns (aelf.Address) {
option (aelf.is_view) = true;
}

// Query the name of the primary Token.
rpc GetPrimaryTokenSymbol (google.protobuf.Empty) returns (google.protobuf.StringValue) {
option (aelf.is_view) = true;
}

// Query the coefficient of the transaction fee calculation formula.
rpc GetCalculateFeeCoefficientsForContract (google.protobuf.Int32Value) returns (CalculateFeeCoefficients) {
option (aelf.is_view) = true;
}

// Query the coefficient of the transaction fee calculation formula.
rpc GetCalculateFeeCoefficientsForSender (google.protobuf.Empty) returns (CalculateFeeCoefficients) {
option (aelf.is_view) = true;
}

// Query tokens that can pay transaction fees.
rpc GetSymbolsToPayTxSizeFee (google.protobuf.Empty) returns (SymbolListToPayTxSizeFee){
option (aelf.is_view) = true;
}

// Query the hash of the last input of ClaimTransactionFees.
rpc GetLatestTotalTransactionFeesMapHash (google.protobuf.Empty) returns (aelf.Hash){
option (aelf.is_view) = true;
}

// Query the hash of the last input of DonateResourceToken.
rpc GetLatestTotalResourceTokensMapsHash (google.protobuf.Empty) returns (aelf.Hash){
option (aelf.is_view) = true;
}
rpc IsTokenAvailableForMethodFee (google.protobuf.StringValue) returns (google.protobuf.BoolValue) {
option (aelf.is_view) = true;
}
rpc GetReservedExternalInfoKeyList (google.protobuf.Empty) returns (StringList) {
option (aelf.is_view) = true;
}

rpc GetTransactionFeeDelegationsOfADelegatee(GetTransactionFeeDelegationsOfADelegateeInput) returns(TransactionFeeDelegations){
option (aelf.is_view) = true;
}

rpc GetTokenAlias (google.protobuf.StringValue) returns (google.protobuf.StringValue) {
option (aelf.is_view) = true;
}

rpc GetSymbolByAlias (google.protobuf.StringValue) returns (google.protobuf.StringValue) {
option (aelf.is_view) = true;
}
}

message TokenInfo {
// The symbol of the token.f
string symbol = 1;
// The full name of the token.
string token_name = 2;
// The current supply of the token.
int64 supply = 3;
// The total supply of the token.
int64 total_supply = 4;
// The precision of the token.
int32 decimals = 5;
// The address that has permission to issue the token.
aelf.Address issuer = 6;
// A flag indicating if this token is burnable.
bool is_burnable = 7;
// The chain id of the token.
int32 issue_chain_id = 8;
// The amount of issued tokens.
int64 issued = 9;
// The external information of the token.
ExternalInfo external_info = 10;
// The address that owns the token.
aelf.Address owner = 11;
}

message ExternalInfo {
map<string, string> value = 1;
}

message CreateInput {
// The symbol of the token.
string symbol = 1;
// The full name of the token.
string token_name = 2;
// The total supply of the token.
int64 total_supply = 3;
// The precision of the token
int32 decimals = 4;
// The address that has permission to issue the token.
aelf.Address issuer = 5;
// A flag indicating if this token is burnable.
bool is_burnable = 6;
// A whitelist address list used to lock tokens.
repeated aelf.Address lock_white_list = 7;
// The chain id of the token.
int32 issue_chain_id = 8;
// The external information of the token.
ExternalInfo external_info = 9;
// The address that owns the token.
aelf.Address owner = 10;
}

message SetPrimaryTokenSymbolInput {
// The symbol of the token.
string symbol = 1;
}

message IssueInput {
// The token symbol to issue.
string symbol = 1;
// The token amount to issue.
int64 amount = 2;
// The memo.
string memo = 3;
// The target address to issue.
aelf.Address to = 4;
}

message TransferInput {
// The receiver of the token.
aelf.Address to = 1;
// The token symbol to transfer.
string symbol = 2;
// The amount to to transfer.
int64 amount = 3;
// The memo.
string memo = 4;
}

message LockInput {
// The one want to lock his token.
aelf.Address address = 1;
// Id of the lock.
aelf.Hash lock_id = 2;
// The symbol of the token to lock.
string symbol = 3;
// a memo.
string usage = 4;
// The amount of tokens to lock.
int64 amount = 5;
}

message UnlockInput {
// The one want to un-lock his token.
aelf.Address address = 1;
// Id of the lock.
aelf.Hash lock_id = 2;
// The symbol of the token to un-lock.
string symbol = 3;
// a memo.
string usage = 4;
// The amount of tokens to un-lock.
int64 amount = 5;
}

message TransferFromInput {
// The source address of the token.
aelf.Address from = 1;
// The destination address of the token.
aelf.Address to = 2;
// The symbol of the token to transfer.
string symbol = 3;
// The amount to transfer.
int64 amount = 4;
// The memo.
string memo = 5;
}

message ApproveInput {
// The address that allowance will be increased.
aelf.Address spender = 1;
// The symbol of token to approve.
string symbol = 2;
// The amount of token to approve.
int64 amount = 3;
}
message BatchApproveInput {
repeated ApproveInput value = 1;
}

message UnApproveInput {
// The address that allowance will be decreased.
aelf.Address spender = 1;
// The symbol of token to un-approve.
string symbol = 2;
// The amount of token to un-approve.
int64 amount = 3;
}

message BurnInput {
// The symbol of token to burn.
string symbol = 1;
// The amount of token to burn.
int64 amount = 2;
}

message ChargeResourceTokenInput {
// Collection of charge resource token, Symbol->Amount.
map<string, int64> cost_dic = 1;
// The sender of the transaction.
aelf.Address caller = 2;
}

message TransactionFeeBill {
// The transaction fee dictionary, Symbol->fee.
map<string, int64> fees_map = 1;
}

message TransactionFreeFeeAllowanceBill {
// The transaction free fee allowance dictionary, Symbol->fee.
map<string, int64> free_fee_allowances_map = 1;
}

message CheckThresholdInput {
// The sender of the transaction.
aelf.Address sender = 1;
// The threshold to set, Symbol->Threshold.
map<string, int64> symbol_to_threshold = 2;
// Whether to check the allowance.
bool is_check_allowance = 3;
}

message GetTokenInfoInput {
// The symbol of token.
string symbol = 1;
}

message GetBalanceInput {
// The symbol of token.
string symbol = 1;
// The target address of the query.
aelf.Address owner = 2;
}

message GetBalanceOutput {
// The symbol of token.
string symbol = 1;
// The target address of the query.
aelf.Address owner = 2;
// The balance of the owner.
int64 balance = 3;
}

message GetAllowanceInput {
// The symbol of token.
string symbol = 1;
// The address of the token owner.
aelf.Address owner = 2;
// The address of the spender.
aelf.Address spender = 3;
}

message GetAllowanceOutput {
// The symbol of token.
string symbol = 1;
// The address of the token owner.
aelf.Address owner = 2;
// The address of the spender.
aelf.Address spender = 3;
// The amount of allowance.
int64 allowance = 4;
}

message CrossChainTransferInput {
// The receiver of transfer.
aelf.Address to = 1;
// The symbol of token.
string symbol = 2;
// The amount of token to transfer.
int64 amount = 3;
// The memo.
string memo = 4;
// The destination chain id.
int32 to_chain_id = 5;
// The chain id of the token.
int32 issue_chain_id = 6;
}

message CrossChainReceiveTokenInput {
// The source chain id.
int32 from_chain_id = 1;
// The height of the transfer transaction.
int64 parent_chain_height = 2;
// The raw bytes of the transfer transaction.
bytes transfer_transaction_bytes = 3;
// The merkle path created from the transfer transaction.
aelf.MerklePath merkle_path = 4;
}

message IsInWhiteListInput {
// The symbol of token.
string symbol = 1;
// The address to check.
aelf.Address address = 2;
}

message SymbolToPayTxSizeFee{
// The symbol of token.
string token_symbol = 1;
// The charge weight of primary token.
int32 base_token_weight = 2;
// The new added token charge weight. For example, the charge weight of primary Token is set to 1.
// The newly added token charge weight is set to 10. If the transaction requires 1 unit of primary token,
// the user can also pay for 10 newly added tokens.
int32 added_token_weight = 3;
}

message SymbolListToPayTxSizeFee{
// Transaction fee token information.
repeated SymbolToPayTxSizeFee symbols_to_pay_tx_size_fee = 1;
}

message ChargeTransactionFeesInput {
// The method name of transaction.
string method_name = 1;
// The contract address of transaction.
aelf.Address contract_address = 2;
// The amount of transaction size fee.
int64 transaction_size_fee = 3;
// Transaction fee token information.
repeated SymbolToPayTxSizeFee symbols_to_pay_tx_size_fee = 4;
}

message ChargeTransactionFeesOutput {
// Whether the charge was successful.
bool success = 1;
// The charging information.
string charging_information = 2;
}

message CallbackInfo {
aelf.Address contract_address = 1;
string method_name = 2;
}

message ExtraTokenListModified {
option (aelf.is_event) = true;
// Transaction fee token information.
SymbolListToPayTxSizeFee symbol_list_to_pay_tx_size_fee = 1;
}

message GetLockedAmountInput {
// The address of the lock.
aelf.Address address = 1;
// The token symbol.
string symbol = 2;
// The id of the lock.
aelf.Hash lock_id = 3;
}

message GetLockedAmountOutput {
// The address of the lock.
aelf.Address address = 1;
// The token symbol.
string symbol = 2;
// The id of the lock.
aelf.Hash lock_id = 3;
// The locked amount.
int64 amount = 4;
}

message TokenInfoList {
// List of token information.
repeated TokenInfo value = 1;
}

message GetCrossChainTransferTokenContractAddressInput {
// The chain id.
int32 chainId = 1;
}

message CrossChainCreateTokenInput {
// The chain id of the chain on which the token was created.
int32 from_chain_id = 1;
// The height of the transaction that created the token.
int64 parent_chain_height = 2;
// The transaction that created the token.
bytes transaction_bytes = 3;
// The merkle path created from the transaction that created the transaction.
aelf.MerklePath merkle_path = 4;
}

message InitializeFromParentChainInput {
// The amount of resource.
map<string, int32> resource_amount = 1;
// The token contract addresses.
map<int32, aelf.Address> registered_other_token_contract_addresses = 2;
// The creator the side chain.
aelf.Address creator = 3;
}

message UpdateCoefficientsInput {
// The specify pieces gonna update.
repeated int32 piece_numbers = 1;
// Coefficients of one single type.
CalculateFeeCoefficients coefficients = 2;
}

enum FeeTypeEnum {
READ = 0;
STORAGE = 1;
WRITE = 2;
TRAFFIC = 3;
TX = 4;
}

message CalculateFeePieceCoefficients {
// Coefficients of one single piece.
// The first char is its type: liner / power.
// The second char is its piece upper bound.
repeated int32 value = 1;
}

message CalculateFeeCoefficients {
// The resource fee type, like READ, WRITE, etc.
int32 fee_token_type = 1;
// Coefficients of one single piece.
repeated CalculateFeePieceCoefficients piece_coefficients_list = 2;
}

message AllCalculateFeeCoefficients {
// The coefficients of fee Calculation.
repeated CalculateFeeCoefficients value = 1;
}

message TotalTransactionFeesMap
{
// Token dictionary that charge transaction fee, Symbol->Amount.
map<string, int64> value = 1;
// The hash of the block processing the transaction.
aelf.Hash block_hash = 2;
// The height of the block processing the transaction.
int64 block_height = 3;
}

message TotalResourceTokensMaps {
// Resource tokens to charge.
repeated ContractTotalResourceTokens value = 1;
// The hash of the block processing the transaction.
aelf.Hash block_hash = 2;
// The height of the block processing the transaction.
int64 block_height = 3;
}

message ContractTotalResourceTokens {
// The contract address.
aelf.Address contract_address = 1;
// Resource tokens to charge.
TotalResourceTokensMap tokens_map = 2;
}

message TotalResourceTokensMap
{
// Resource token dictionary, Symbol->Amount.
map<string, int64> value = 1;
}

message StringList {
repeated string value = 1;
}

message TransactionFeeDelegations{
// delegation, symbols and its' amount
map<string, int64> delegations = 1;
// height when added
int64 block_height = 2;
//Whether to pay transaction fee continuously
bool isUnlimitedDelegate = 3;
}

message TransactionFeeDelegatees{
map<string,TransactionFeeDelegations> delegatees = 1;
}

message SetTransactionFeeDelegationsInput {
// the delegator address
aelf.Address delegator_address = 1;
// delegation, symbols and its' amount
map<string, int64> delegations = 2;
}

message SetTransactionFeeDelegationsOutput {
bool success = 1;
}

message RemoveTransactionFeeDelegatorInput{
// the delegator address
aelf.Address delegator_address = 1;
}

message RemoveTransactionFeeDelegateeInput {
// the delegatee address
aelf.Address delegatee_address = 1;
}

message GetTransactionFeeDelegationsOfADelegateeInput {
aelf.Address delegatee_address = 1;
aelf.Address delegator_address = 2;
}

message GetTransactionFeeDelegateesInput {
aelf.Address delegator_address = 1;
}

message GetTransactionFeeDelegateesOutput {
repeated aelf.Address delegatee_addresses = 1;
}

message SetSymbolAliasInput {
string symbol = 1;
string alias = 2;
}

// Events

message Transferred {
option (aelf.is_event) = true;
// The source address of the transferred token.
aelf.Address from = 1 [(aelf.is_indexed) = true];
// The destination address of the transferred token.
aelf.Address to = 2 [(aelf.is_indexed) = true];
// The symbol of the transferred token.
string symbol = 3 [(aelf.is_indexed) = true];
// The amount of the transferred token.
int64 amount = 4;
// The memo.
string memo = 5;
}

message Approved {
option (aelf.is_event) = true;
// The address of the token owner.
aelf.Address owner = 1 [(aelf.is_indexed) = true];
// The address that allowance be increased.
aelf.Address spender = 2 [(aelf.is_indexed) = true];
// The symbol of approved token.
string symbol = 3 [(aelf.is_indexed) = true];
// The amount of approved token.
int64 amount = 4;
}

message UnApproved {
option (aelf.is_event) = true;
// The address of the token owner.
aelf.Address owner = 1 [(aelf.is_indexed) = true];
// The address that allowance be decreased.
aelf.Address spender = 2 [(aelf.is_indexed) = true];
// The symbol of un-approved token.
string symbol = 3 [(aelf.is_indexed) = true];
// The amount of un-approved token.
int64 amount = 4;
}

message Burned
{
option (aelf.is_event) = true;
// The address who wants to burn token.
aelf.Address burner = 1 [(aelf.is_indexed) = true];
// The symbol of burned token.
string symbol = 2 [(aelf.is_indexed) = true];
// The amount of burned token.
int64 amount = 3;
}

message ChainPrimaryTokenSymbolSet {
option (aelf.is_event) = true;
// The symbol of token.
string token_symbol = 1;
}

message CalculateFeeAlgorithmUpdated {
option (aelf.is_event) = true;
// All calculate fee coefficients after modification.
AllCalculateFeeCoefficients all_type_fee_coefficients = 1;
}

message RentalCharged {
option (aelf.is_event) = true;
// The symbol of rental fee charged.
string symbol = 1;
// The amount of rental fee charged.
int64 amount = 2;
// The payer of rental fee.
aelf.Address payer = 3;
// The receiver of rental fee.
aelf.Address receiver = 4;
}

message RentalAccountBalanceInsufficient {
option (aelf.is_event) = true;
// The symbol of insufficient rental account balance.
string symbol = 1;
// The balance of the account.
int64 amount = 2;
}

message TokenCreated {
option (aelf.is_event) = true;
// The symbol of the token.
string symbol = 1;
// The full name of the token.
string token_name = 2;
// The total supply of the token.
int64 total_supply = 3;
// The precision of the token.
int32 decimals = 4;
// The address that has permission to issue the token.
aelf.Address issuer = 5;
// A flag indicating if this token is burnable.
bool is_burnable = 6;
// The chain id of the token.
int32 issue_chain_id = 7;
// The external information of the token.
ExternalInfo external_info = 8;
// The address that owns the token.
aelf.Address owner = 9;
}

message Issued {
option (aelf.is_event) = true;
// The symbol of issued token.
string symbol = 1;
// The amount of issued token.
int64 amount = 2;
// The memo.
string memo = 3;
// The issued target address.
aelf.Address to = 4;
}

message CrossChainTransferred {
option (aelf.is_event) = true;
// The source address of the transferred token.
aelf.Address from = 1;
// The destination address of the transferred token.
aelf.Address to = 2;
// The symbol of the transferred token.
string symbol = 3;
// The amount of the transferred token.
int64 amount = 4;
// The memo.
string memo = 5;
// The destination chain id.
int32 to_chain_id = 6;
// The chain id of the token.
int32 issue_chain_id = 7;
}

message CrossChainReceived {
option (aelf.is_event) = true;
// The source address of the transferred token.
aelf.Address from = 1;
// The destination address of the transferred token.
aelf.Address to = 2;
// The symbol of the received token.
string symbol = 3;
// The amount of the received token.
int64 amount = 4;
// The memo.
string memo = 5;
// The destination chain id.
int32 from_chain_id = 6;
// The chain id of the token.
int32 issue_chain_id = 7;
// The parent chain height of the transfer transaction.
int64 parent_chain_height = 8;
// The id of transfer transaction.
aelf.Hash transfer_transaction_id =9;
}

message TransactionFeeDelegationAdded {
option (aelf.is_event) = true;
aelf.Address delegator = 1 [(aelf.is_indexed) = true];
aelf.Address delegatee = 2 [(aelf.is_indexed) = true];
aelf.Address caller = 3 [(aelf.is_indexed) = true];
}

message TransactionFeeDelegationCancelled {
option (aelf.is_event) = true;
aelf.Address delegator = 1 [(aelf.is_indexed) = true];
aelf.Address delegatee = 2 [(aelf.is_indexed) = true];
aelf.Address caller = 3 [(aelf.is_indexed) = true];
}

message SymbolAliasAdded {
option (aelf.is_event) = true;
string symbol = 1 [(aelf.is_indexed) = true];
string alias = 2 [(aelf.is_indexed) = true];
}

message SymbolAliasDeleted {
option (aelf.is_event) = true;
string symbol = 1 [(aelf.is_indexed) = true];
string alias = 2 [(aelf.is_indexed) = true];
}
tip

You can acquire the latest token_contract.proto from the aelf GitHub repository.

Step 2.2: Create Contract Reference State

In this step, we will create a reference state for the token contract within our lottery game contract.

Instructions

  1. Create a new file: Open your project directory and navigate to the src folder. Create a new file named ContractReferences.cs.

  2. Add the reference state code: Copy and paste the following code snippet into the newly created ContractReferences.cs file. This code establishes a reference to the MultiToken contract within your lottery game contract.

using AElf.Contracts.MultiToken;

namespace AElf.Contracts.LotteryGame
{
public partial class LotteryGameState
{
internal TokenContractContainer.TokenContractReferenceState TokenContract { get; set; }
}
}

Explanation

  • The using AElf.Contracts.MultiToken; directive imports the necessary namespace for the MultiToken contract.
  • Inside this class, we declare an internal property TokenContract of type TokenContractContainer.TokenContractReferenceState. This property will hold a reference to the MultiToken contract.

By following these steps, we have successfully created a contract state that references the MultiToken contract. The next step will involve initializing this reference state.